package controllers

import (
	"baokaobang/datasourse"
	"baokaobang/models"
	"baokaobang/utils"
	"fmt"
	"github.com/go-xorm/xorm"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/sessions"
	"math/rand"
	"strings"
	"time"
)

type Volunteer struct {
	Ctx iris.Context
}

// 志愿模拟
func (c *Volunteer) PostSimulation() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "mini")
	score := c.Ctx.PostValue("score")
	universityCodes := strings.TrimSpace(c.Ctx.PostValue("universityCode"))
	universityCode := strings.Split(universityCodes, ",")
	majorNames := strings.TrimSpace(c.Ctx.PostValue("majorName"))
	majorName := strings.Split(majorNames, ",")

	if len(score) <= 0 {
		return utils.CommonRes(1000, "请输入总成绩", "")
	}
	if len(universityCode[0]) <= 0 {
		return utils.CommonRes(1000, "请输入第一志愿院校招生代码", "")
	}
	if len(majorName[0]) <= 0 {
		return utils.CommonRes(1000, "请输入第一志愿专业名称", "")
	}
	if len(universityCode[1]) <= 0 {
		return utils.CommonRes(1000, "请输入第二志愿院校招生代码", "")
	}
	if len(majorName[1]) <= 0 {
		return utils.CommonRes(1000, "请输入第二志愿专业名称", "")
	}
	if len(universityCode[2]) <= 0 {
		return utils.CommonRes(1000, "请输入第三志愿院校代码", "")
	}
	if len(majorName[2]) <= 0 {
		return utils.CommonRes(1000, "请输入第三志愿专业名称", "")
	}
	if len(universityCode[3]) <= 0 {
		return utils.CommonRes(1000, "请输入第四志愿院校招生代码", "")
	}
	if len(majorName[3]) <= 0 {
		return utils.CommonRes(1000, "请输入第四志愿专业名称", "")
	}

	var userId int64
	if strings.EqualFold(channel, "wechat") {
		token := c.Ctx.GetHeader("token")
		claims, err := utils.ParseToken(token)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("解析token出错：%s", err.Error()), "")
		}
		userId = utils.Atoi64(claims.Id)
	} else {
		session := sessions.Get(c.Ctx)
		userId, _ = session.GetInt64(fmt.Sprintf("%sUserId", channel))
	}

	var err error
	var db *xorm.Engine
	var ok bool

	db, err = datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	sess := db.NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("数据库事务开启失败：%s", err.Error()), "")
	}

	user := new(models.User)
	ok, err = db.ID(userId).Get(user)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法获取当前登录用户信息：%s", err.Error()), "")
	}
	if !ok {
		return utils.CommonRes(1000, "无法获取当前登录用户信息", "")
	}
	userSubject := user.Subject

	year := utils.Atoi(time.Now().Format("2006"))

	rank := new(models.Rank)
	ok, err = sess.Where("year = ? and subject = ? and score = ?", year, userSubject, score).Get(rank)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("您当前的分数没有匹配到对应的位次：%s", err.Error()), "")
	}
	if !ok {
		return utils.CommonRes(1000, "您当前的分数没有匹配到对应的位次", "")
	}
	rankNum := utils.Atoi(strings.Split(rank.Section, "~")[1])

	rand.Seed(time.Now().UnixNano())

	for i := 0; i < 4; i++ {
		college := new(models.College)
		ok, err = sess.Where("`code` = ?", universityCode[i]).Get(college)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("根据院校招生代码查询院校出错：%s", err.Error()), "")
		}
		if !ok {
			return utils.CommonRes(1000, fmt.Sprintf("不存在%s", universityCode[i]), "")
		}

		var probability float64
		totalCount, err := sess.Table(new(models.AdmissionData)).
			Where("`college_id` = ? and `subject` = ? and `major_name` like ?", college.Id, userSubject, fmt.Sprintf("%%%s%%", strings.TrimSpace(majorName[i]))).
			Count()
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("数据查询出错：%s", err.Error()), "")
		}
		if totalCount <= 0 {
			//probability = utils.Atof64(fmt.Sprintf("%.2f", rand.Float64())) + utils.Atof64(fmt.Sprintf("%d", rand.Intn(9)))
			probability = 0
		} else {
			probability = utils.Atof64(fmt.Sprintf("%.2f", rand.Float64()))
			matchCount, err := sess.Table(new(models.AdmissionData)).
				Where("`college_id` = ? and `subject` = ? and `min_score_high` >= ? and `major_name` like ?", college.Id, userSubject, rankNum, fmt.Sprintf("%%%s%%", strings.TrimSpace(majorName[i]))).
				Count()
			if err != nil {
				return utils.CommonRes(1000, fmt.Sprintf("数据查询出错：%s", err.Error()), "")
			}
			probability = utils.Atof64(fmt.Sprintf("%.2f", float64(matchCount) / float64(totalCount))) * 100 + probability
		}

		if probability >= 100 {
			probability = 99.99
		}

		volunteer := new(models.Volunteer)
		volunteer.UserId = userId
		volunteer.CollegeId = college.Id
		volunteer.Year = year
		volunteer.MajorName = majorName[i]
		volunteer.Score = utils.Atoi(score)
		volunteer.Sort = i + 1
		volunteer.Probability = probability
		_, err = sess.InsertOne(volunteer)
		if err != nil {
			return utils.CommonRes(1000, fmt.Sprintf("操作失败：%s", err.Error()), "")
		}
	}

	sess.Commit()

	return utils.CommonRes(20000, "操作成功", "")
}

// 志愿模拟结果
func (c *Volunteer) PostResult() interface{} {
	channel := c.Ctx.PostValueDefault("channel", "mini")

	session := sessions.Get(c.Ctx)
	userId, _ := session.GetInt64(fmt.Sprintf("%sUserId", channel))

	var err error
	var db *xorm.Engine

	db, err = datasourse.NewMasterOrm()
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法连接数据库：%s", err.Error()), "")
	}

	volunteerList := make([]models.VolunteerObj, 0)
	err = db.Table("volunteer").Alias("v").
		Join("INNER", []string{"college", "c"}, "v.college_id = c.id").
		Join("INNER", []string{"university", "u"}, "c.university_id = u.id").
		Where("v.user_id = ?", userId).Asc("v.sort").Find(&volunteerList)
	if err != nil {
		return utils.CommonRes(1000, fmt.Sprintf("无法获取志愿列表:%s", err.Error()), "")
	}

	for i, item := range volunteerList {
		universityLabelList := make([]models.UniversityLabelObj, 0)
		db.Table("university_label").Alias("ul").
			Join("INNER", []string{"label", "l"}, "ul.label_id = l.id").
			Where("ul.university_id = ?", item.UniversityData.Id).Find(&universityLabelList)
		volunteerList[i].UniversityData.LabelList = universityLabelList
	}

	return utils.CommonRes(20000, "成功获取志愿列表", volunteerList)
}
